package com.mjk.manager.workflow.parser.sql.parse.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.mjk.common.base.error.BizException;
import com.mjk.common.core.jdbc.service.plus.idbservice.BeeDBService;
import com.mjk.common.core.jdbc.service.plus.wrap.BeeQueryWrapper;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.tools.springextend.BeeApplicationListener;
import com.mjk.common.tools.springextend.BeeSpringBean;
import com.mjk.common.util.ClobUtils;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.StrUtils;
import com.mjk.manager.magicapi.core.core.event.EventAction;
import com.mjk.manager.magicapi.core.core.event.FileEvent;
import com.mjk.manager.magicapi.core.core.model.MagicEntity;
import com.mjk.manager.workflow.parser.sql.model.MagicApiModel;
import com.mjk.manager.workflow.parser.sql.parse.ILiteParse;
import com.ql.util.express.ExpressRunner;
import com.ql.util.express.InstructionSet;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.FlowBus;
import groovy.lang.GroovyClassLoader;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * 对于magic api中的script 解析 并注册为对应的 spring类
 */
@Component
public class MagicParse implements BeeApplicationListener, ILiteParse {
    @Autowired
    private FlowExecutor flowExecutor;
    /**
     * 上下文
     */
    private ConfigurableApplicationContext context;
    /**
     * 保存的业务流类
     */
    //final Map<String,Object> magicFlowMap = new HashMap<>();
    /**
     * 分隔符
     */
    String separatorWithCRLF = "================================";
    /**
     * magic api 业务流 代码生成
     */
    public static final  String MAGIC_FLOW = """
            package com.mjk.manager.workflow.component;\r
            import org.ssssssss.script.MagicScriptContext;\r
            import com.mjk.manager.workflow.component.dto.BeeLiteFlowContext;\r
            import com.mjk.manager.magicapi.core.core.config.MagicConfiguration;\r
            import com.mjk.manager.magicapi.core.core.model.MagicEntity;\r
            import com.mjk.manager.magicapi.core.utils.ScriptManager;\r
            import java.lang.reflect.Method;\r
            import com.mjk.common.util.BeanUtils;\r
            import com.mjk.common.util.ReflectionUtils;\r
            import com.yomahub.liteflow.annotation.LiteflowComponent;\r
            import com.yomahub.liteflow.core.NodeComponent;\r
            @LiteflowComponent(name = "%s")\r
            public class %s extends NodeComponent implements BaseFlow{\r
                @Override\r
                public void process() throws Exception {\r
                    String script = "%s";
                    BeeLiteFlowContext dto = this.getContextBean(BeeLiteFlowContext.class);
                    Object result = ScriptManager.executeScript(script, conver2Context(dto));
                    dto.setData("%s",result);
                }\r
            }
    """;
    /**
     * 生成magicapi liteflow调用流程信息
     * @param chainMap
     */
    public void parse(Map<String, String> chainMap) {
        for(Map.Entry<String,String> entry : chainMap.entrySet()) {
            String express = entry.getValue();
            ExpressRunner runner = new ExpressRunner();
            try {
                InstructionSet set = runner.getInstructionSetFromLocalCache(express);
                //获取节点信息
                if(null!=set && !ObjectUtils.isEmpty(set.getOutAttrNames())) {
                    for(String str : set.getOutAttrNames()) {
                        getEntity(str);
                    }
                }
            }catch(Exception e) {
                throw new BizException("node parse error" + ExceptionUtil.getMessage(e));
            }
        }
    }
    public MagicEntity getEntity(String attrName){
        if(attrName.contains("@")) {
            String parentPath = attrName.substring(0,attrName.lastIndexOf("@"));
            String path = attrName.substring(attrName.lastIndexOf("@")+1);
            BeeQueryWrapper wrapper = new BeeQueryWrapper(new MagicApiModel());
            wrapper.eq(MagicApiModel::getParent_path, parentPath).eq(MagicApiModel::getPath,path);
            BeeDBService beeDBService = BeeSpringBean.getBean(BeeDBService.class);
            MagicApiModel model = (MagicApiModel)beeDBService.findOneByWrapper(wrapper);
            String content = ClobUtils.clobToString(model.getFile_content());
            String json = content.substring(0,content.indexOf(separatorWithCRLF));
            String script = content.substring(content.indexOf(separatorWithCRLF)+separatorWithCRLF.length());
            MagicEntity entity = GsonUtils.json2Bean(json,MagicEntity.class);
            entity.setScript(script);
            buildFlowByAttrName(entity,model);
            return entity;
        }
        return null;
    }
    public synchronized void  buildFlowByAttrName(MagicEntity entity,MagicApiModel model) {
            String className = model.getLiteComp().replace("@","");
            //查看spring容器中是否已经存在改bean 如果存在需要卸载
            BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) context.getBeanFactory();
            if(this.context.containsBean(model.getLiteComp())){
                beanFactory.removeBeanDefinition(model.getLiteComp());
                FlowBus.getNodeMap().remove(model.getLiteComp());
                flowExecutor.reloadRule();
            }
            String script = entity.getScript().replace("\"", "\\\"");
            String clazzStr = String.format(MAGIC_FLOW, model.getLiteComp(), StrUtils.toUpperCaseFirstOne(className),script,className);
            try(GroovyClassLoader groovyClassLoader = new GroovyClassLoader();) {
                Class clazz = groovyClassLoader.parseClass(clazzStr);
                BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
                BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
                beanFactory.registerBeanDefinition(model.getLiteComp(), beanDefinition);
                FlowBus.addManagedNode(model.getLiteComp());
            }catch (Exception e){
                BizLogger.error(e);
            }

    }
    @EventListener(condition = "#event.type == 'api'")
    public void onFileEvent(FileEvent event) {
        //只处理save 和 update
        if(event.getAction().equals(EventAction.SAVE) || event.getAction().equals(EventAction.CREATE)){
//            MagicApiModel model = new MagicApiModel();
//            event.getEntity().setScript(StrUtils.format(event.getEntity().getScript()));
//            model.setLiteComp(event.getEntity().getGroupName()+"@"+event.getEntity().getePath());
//            buildFlowByAttrName(event.getEntity(),model);
        }
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = (ConfigurableApplicationContext) applicationContext;
    }
}
